﻿using System.Collections.ObjectModel;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Views;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Wimm.Common.Entities;
using Wimm.Common.Interfaces.Services;
using System.Windows.Input;

namespace Wimm.UI.ViewModels
{
    public class AddIncomeViewModel : ViewModelBase
    {
        private Decimal      _amount;
        private IncomeSource _selectedSource;
        private DateTimeOffset _incomeTime;
        public  String       _incomeComment;
        private int _userId;
        private IIncomeService _incomeService;
        private INavigationService _navigationService;

        private ObservableCollection<IncomeSourceBindingModel> _sourceincome;
        private IncomeSourceBindingModel _incomeSource1;
        private string _language;

        private readonly RelayCommand _addIncomeCommand;

        private IReadOnlyDictionary<int, Icon> _icons;

        public AddIncomeViewModel(IIncomeService incomeService, INavigationService navigationService, int UserId, string lang)
        {
            if (incomeService == null)
                throw new ArgumentNullException("incomeService");

            if (navigationService == null)
                throw new ArgumentNullException("navigationService");

            _addIncomeCommand = new RelayCommand(DoAddIncome, CanAddIncome);
            _userId = UserId;
            _incomeService = incomeService;
            _navigationService = navigationService;
            _sourceincome = new ObservableCollection<IncomeSourceBindingModel>();
            this._language = lang;

            this.Time = DateTime.Today;
            this.Amount = 0.00m;
            this.Comment = "";

            LoadData();
        }

        #region LoadData
        private bool loading = false;

        public async void LoadData()
        {
            if (loading)
                return;

            try
            {
                loading = true;

                if (_icons == null)
                {
                    _icons = await _incomeService.LoadSourceIcons();
                }

                int? parentId = this.SelectedSource == null ? (int?)null : this.SelectedSource.Id;

                if (parentId.HasValue && parentId.Value == -1)
                    parentId = null;

                IEnumerable<IncomeSource> source = await _incomeService.LoadSources(parentId);

                if (source.Count() > 0)
                {
                    ObservableCollection<IncomeSource> cats = new ObservableCollection<IncomeSource>(source);

                    this.Sourceincome.Clear();

                    if (parentId.HasValue)
                    {
                        //add fake "return" category
                        IncomeSource incomeCat = new IncomeSource("Return",66,"Return", null, -1);
                        this.Sourceincome.Add(new IncomeSourceBindingModel(incomeCat, _icons[incomeCat.IconId.Value], this._language));


                    }

                    foreach (IncomeSource ec in cats)
                        this.Sourceincome.Add(new IncomeSourceBindingModel(ec, _icons[ec.IconId.Value], this._language));
                }
            }
            finally
            {
                loading = false;
            }
        }
        #endregion

        private IEnumerable<IncomeSource> _allSources;

        public  IEnumerable<IncomeSource>  AllSources
        {
            get { return _allSources; }
            set { Set<IEnumerable<IncomeSource>>(() => AllSources, ref _allSources, value); }
        }

        private bool CanAddIncome()
        {
            return _amount > 0 && _incomeSource1 != null;
        }

        private async void DoAddIncome()
        {
            Income income = new Income(_incomeTime.DateTime, Convert.ToInt32(_amount), _userId, _incomeSource1.Id, _incomeComment);

            await _incomeService.InsertIncome(income);

            this.SelectedSource = null;
            this.Amount         = 0;
            this.Time           = DateTime.Today;
            this.Comment        = "";

            _navigationService.NavigateTo("hub", typeof(HubPage));
        }
        
        public ICommand AddIncomeCommand
        {
            get { return _addIncomeCommand; }
        }


        public IncomeSourceBindingModel SelectedSource
        {
            get { return _incomeSource1; }
            set
            {
                Set<IncomeSourceBindingModel>(() => SelectedSource, ref _incomeSource1, value);
                _addIncomeCommand.RaiseCanExecuteChanged();
                LoadData();
            }
        }
        public String SelectedSourceName
        {
            get
            {
                return this.SelectedSource == null ? "Not Selected" : this.SelectedSource.Name;
            }
        }
        public Decimal Amount
        {
            get { return _amount; }
            set 
            { 
                Set<Decimal>(() => Amount, ref _amount, value);
                _addIncomeCommand.RaiseCanExecuteChanged();
            }
        }

        public DateTimeOffset Time
        {
            get { return _incomeTime; }
            set { Set<DateTimeOffset>(() => Time, ref _incomeTime, value); }
        }

        public ObservableCollection<IncomeSourceBindingModel> Sourceincome
        {
            get
            {
                return _sourceincome;
            }
            set
            {
                Set<ObservableCollection<IncomeSourceBindingModel>>(() => Sourceincome, ref _sourceincome, value);
            }
        }

        public String Comment
        {
            get { return _incomeComment; }
            set
            {
                Set<String>(() => Comment, ref _incomeComment, value);
            }
        }

        public void SetLanguage(string lang)
        {
            _language = lang;
            this.LoadData();
        }
    }
}
